﻿/*************************************************************************
 *  Copyright © 2023-2030 Administrator. All rights reserved.
 *------------------------------------------------------------------------
 *  公司：DefaultCompany
 *  项目：CustomPackageManager
 *  文件：SVNHelper.cs
 *  作者：Administrator
 *  日期：2024/9/28 22:10:41
 *  功能：Nothing
*************************************************************************/

using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEditor;
using UnityEngine;
using static UnityEditor.EditorApplication;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using PackageInfo = UnityEditor.PackageManager.PackageInfo;

namespace SVNPackageManager.Editor
{
    [System.Serializable]
    public class PacakgeStateMessage
    {
        public string packageItemID;
        public string message;
        public bool isSuccess;
        public string data;
    }

    public class PackageInstaller
    {
        /// <summary>
        /// 从本地路径安装包
        /// 1、可以通过本地文件夹安装包，格式file:pathtopackagefolder，如file:E:/UPMProject/UPM/com.fxb.test
        /// 2、从.tgz文件安装包，格式file:pathtopackage.tgz，如file:E:/UPMProject/UPM/com.fxb.test.tgz
        /// </summary>
        /// <param name="packagePath"></param>
        public static Task<PacakgeStateMessage> InstallPackageFromDisk(string packagePath)
        {
            TaskCompletionSource<PacakgeStateMessage> taskCompletionSource = new TaskCompletionSource<PacakgeStateMessage>();

            PacakgeStateMessage state = new PacakgeStateMessage();

            //从本地文件夹安装包
            if (Directory.Exists(packagePath))
            {
                // 构造package.json文件的完整路径
                string packageJsonPath = Path.Combine(packagePath, "package.json");

                // 检查package.json文件是否存在
                if (!File.Exists(packageJsonPath))
                {
                    state.message = "The provided folder does not contain a valid 'package.json' file and is not a valid Unity package.";
                    state.isSuccess = false;
                    Debug.LogError(state.message);
                    taskCompletionSource.SetResult(state);
                    return taskCompletionSource.Task;
                }
            }
            //从.tgz文件安装包
            else if (File.Exists(packagePath))
            {
                if (!packagePath.EndsWith(".tgz"))
                {
                    state.message = $"{packagePath} file is not a valid Unity package.";
                    state.isSuccess = false;
                    Debug.LogError(state.message);
                    taskCompletionSource.SetResult(state);
                    return taskCompletionSource.Task;
                }
            }
            else
            {
                state.message = $"The package at path {packagePath} does not exist.";
                state.isSuccess = false;
                Debug.LogError(state.message);
                taskCompletionSource.SetResult(state);
                return taskCompletionSource.Task;
            }

            // 构建正确的标识符
            string identifier = $"file:{packagePath}";
            // 如果存在package.json，那么这是一个有效的包，可以继续安装
            AddRequest request = Client.Add(identifier);
            CallbackFunction onAddUpdate = null;
            onAddUpdate = () =>
            {
                if (request.IsCompleted)
                {
                    if (request.Status == StatusCode.Success)
                    {
                        state.message = $"Package from {packagePath} installed successfully.";
                        state.isSuccess = true;
                        Debug.Log(state.message);
                        taskCompletionSource.SetResult(state);
                    }
                    else
                    {
                        state.message = $"{request.Error.message}";
                        state.isSuccess = false;
                        Debug.LogError($"Failed to install package from {packagePath}: {request.Error.message}");
                        taskCompletionSource.SetResult(state);
                    }

                    // 移除更新回调
                    EditorApplication.update -= onAddUpdate;
                }
            };

            // 注册更新事件
            EditorApplication.update += onAddUpdate;

            return taskCompletionSource.Task;
        }

        public static Task<PacakgeStateMessage> RemovePackage(string packageName)
        {
            TaskCompletionSource<PacakgeStateMessage> taskCompletionSource = new TaskCompletionSource<PacakgeStateMessage>();

            PacakgeStateMessage state = new PacakgeStateMessage();

            RemoveRequest request = Client.Remove(packageName);

            CallbackFunction OnUpdateRemovePackage = null;

            // 使用闭包来捕获当前的 request 和 packageName
            OnUpdateRemovePackage = () =>
            {
                if (request.IsCompleted)
                {
                    if (request.Status == StatusCode.Success)
                    {
                        state.message = $"Package {packageName} removed successfully.";
                        state.isSuccess = true;
                        Debug.Log(state.message);
                        taskCompletionSource.SetResult(state);
                    }
                    else
                    {
                        state.message = $"{request.Error.message}";
                        state.isSuccess = false;
                        Debug.LogError($"Failed to remove package {packageName}: {request.Error.message}");
                        taskCompletionSource.SetResult(state);
                    }

                    // 移除更新回调
                    EditorApplication.update -= OnUpdateRemovePackage;
                }
            };

            EditorApplication.update += OnUpdateRemovePackage;

            return taskCompletionSource.Task;
        }

        /// <summary>
        /// Checks if a package with the specified name and version is installed.
        /// </summary>
        /// <param name="packageName">The name of the package.</param>
        /// <param name="packageVersion">The version of the package.</param>
        /// <returns>True if the package is installed, false otherwise.</returns>
        public static Task<PackageInfo> IsPackageInstalled(string packageName, string packageVersion)
        {
            // 创建一个 List 请求
            ListRequest listRequest = Client.List(true);

            CallbackFunction OnUpdateList = null;

            PackageInfo packageInfo = null;

            TaskCompletionSource<PackageInfo> taskCompletionSource = new TaskCompletionSource<PackageInfo>();

            OnUpdateList = () =>
            {
                if (listRequest.IsCompleted)
                {
                    if (listRequest.Status == StatusCode.Success)
                    {
                        packageInfo = listRequest.Result.FirstOrDefault(item => item.name == packageName && item.version == packageVersion);
                    }
                    else
                    {
                        Debug.LogError($"Failed to list packages. Status code: {listRequest.Status}");
                    }

                    taskCompletionSource.SetResult(packageInfo);

                    // 移除更新回调
                    EditorApplication.update -= OnUpdateList;
                }
            };

            EditorApplication.update += OnUpdateList;

            return taskCompletionSource.Task;
        }
    }
}


